﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Tomato.Allure.Samples
{
	public partial class SolutionCounterForm : Form
	{
		private IVisualStudio m_visualStudio = null;
		private List<string> m_fileFilters = null;

		public SolutionCounterForm( IVisualStudio visualStudio )
		{
			InitializeComponent();

			m_visualStudio = visualStudio;

			m_fileFilters = new List<string>();

			Location = new Point(
				m_visualStudio.MainWindow.Left + m_visualStudio.MainWindow.Width / 2 - Width / 2,
				m_visualStudio.MainWindow.Top + m_visualStudio.MainWindow.Height / 2 - Height / 2 );
		}

		// 솔루션 통계를 실행한다.
		public void Execute()
		{
			listView1.SuspendLayout();

			// 필터
			m_fileFilters.Clear();
			{
				String filterBoxText = textBox1.Text;

				char[] separators = new char[] { ';', ' ' };
				string[] tokens = filterBoxText.Split( separators, StringSplitOptions.RemoveEmptyEntries );
				foreach( string filter in tokens )
				{
					m_fileFilters.Add( filter.Trim() );
				}
			}

			// 통계를 수집한다.
			StatisticsItem solutionStatistics = new StatisticsItem();

			listView1.Items.Clear();
			foreach( IProject project in m_visualStudio.ActiveSolution.Projects )
			{
				if( project.Kind == ProjectKind.VirtualFolder )
				{
					foreach( IProjectItem subProject in project.ProjectItems )
					{
						solutionStatistics.Add( CollectProjectStatistics( subProject.SubProject ) );
					}
				}
				else if( project.Kind == ProjectKind.Misc )
				{
				}
				else
				{
					solutionStatistics.Add( CollectProjectStatistics( project ) );
				}
			}

			listView1.ResumeLayout();

			// 솔루션 이름
			groupBox1.Text = string.Format( "솔루션: {0}", Path.GetFileName( m_visualStudio.ActiveSolution.FileName ) );

			// 솔루션 총 파일 개수
			label_totalFiles.Text = solutionStatistics.FileCount.ToString( "#,###" );
			label_totalLines.Text = solutionStatistics.LineCount.ToString( "#,###" );			
		}

		public void OnOpenedSolution()
		{
		}

		private StatisticsItem CollectProjectStatistics( IProject project )
		{
			StatisticsItem statistics = CollectProjectItemStatistics( project.ProjectItems );

			ListViewItem listViewItem = new ListViewItem( new string[] {
				 project.Name,
				 statistics.FileCount.ToString( "#,###" ),
				 statistics.LineCount.ToString( "#,###" ) } );
			listView1.Items.Add( listViewItem );

			return statistics;
		}

		private StatisticsItem CollectProjectItemStatistics( IProjectItems projectItems )
		{
			StatisticsItem statistics = new StatisticsItem();

			if( projectItems != null )
			{
				foreach( IProjectItem projectItem in projectItems )
				{
					if( projectItem.Kind == ProjectItemKind.PhysicalFile )
					{
						// 필터링
						bool bFiltered = true;
						string fileName = Path.GetFileName( projectItem.GetFileName( 0 ) );
						foreach( string filter in m_fileFilters )
						{
							string regexFilter = @"^" + filter.Replace( ".", @"\." ).Replace( "?", "." ).Replace( "*", ".*" ) + @"$";
							if( System.Text.RegularExpressions.Regex.IsMatch( fileName, regexFilter ) )
							{
								bFiltered = false;
								break;
							}
						}

						if( !bFiltered )
						{
							// 파일 갯수를 세고
							statistics.IncrementFileCount();

							// 파일을 이루는 코드 라인을 센다.
							statistics.AddLineCount( CountFileLines( projectItem.GetFileName( 0 ) ) );
						}
					}

					// 서브 프로젝트 있으면 처리하기.
					if( projectItem.SubProject != null )
					{
						statistics.Add( CollectProjectStatistics( projectItem.SubProject ) );
					}
					// 하위 프로젝트 아이템 있으면 처리하기.
					else
					{
						if( projectItem.ProjectItems != null )
						{
							statistics.Add( CollectProjectItemStatistics( projectItem.ProjectItems ) );
						}
					}
				}
			}

			return statistics;
		}
		//private void StatisticProjectItems(IProjectItems projectItems, out int numFiles, out int numLines)

		private int CountFileLines( String filePath )
		{
			int count = 0;

			try
			{
				// 파일 읽고 라인 수 세기.
				StreamReader streamReader = new StreamReader( filePath );
				while( streamReader.ReadLine() != null )
				{
					count++;
				}
			}
			catch( Exception )
			{ }

			return count;
		}

		// 다시 계산하기 버튼 클릭
		private void button1_Click( object sender, EventArgs e )
		{
			Execute();
		}

		// 닫기 버튼 클릭
		private void button3_Click( object sender, EventArgs e )
		{
			DialogResult = DialogResult.OK;
		}

		private class StatisticsItem
		{
			public int FileCount { get; private set; }

			public int LineCount { get; private set; }

			public StatisticsItem()
			{
				FileCount = 0;
				LineCount = 0;
			}

			public void IncrementFileCount()
			{
				FileCount++;
			}

			public void IncrementLineCount()
			{
				LineCount++;
			}

			public void Reset()
			{
				FileCount = 0;
				LineCount = 0;
			}

			public void Add( StatisticsItem item )
			{
				FileCount += item.FileCount;
				LineCount += item.LineCount;
			}

			public void AddFileCount( int count )
			{
				FileCount += count;
			}

			public void AddLineCount( int count )
			{
				LineCount += count;
			}
		}
	}

}
